package homework.valid;

import homework.valid.validators.BaseValidator;
import homework.valid.validators.ValidateChain;
import homework.valid.validators.impl.RangeValidator;
import homework.valid.validators.parser.DoubleParser;
import homework.valid.validators.parser.IntegerParser;

import java.io.*;

public class ForcedInput {

    private BufferedReader reader;
    private OutputStream outputStream;
    private static ValidateChain intChain;
    private static ValidateChain doubleChain;
    private static ValidateChain uIntChain;
    private static ValidateChain pDoubleChain;

    static {
        IntegerParser intParser = new IntegerParser("输入整数格式有误");
        DoubleParser doubleParser = new DoubleParser("输入实数格式有误");

        intChain = new ValidateChain(intParser);
        doubleChain = new ValidateChain(doubleParser);

        uIntChain = new ValidateChain(intParser);
        pDoubleChain = new ValidateChain(doubleParser);

        BaseValidator unsignedValidator = new RangeValidator("范围有误", 0, Long.MAX_VALUE);
        uIntChain.addValidator(unsignedValidator);
        pDoubleChain.addValidator(unsignedValidator);
    }

    public ForcedInput(InputStream in, OutputStream out) {
        reader = new BufferedReader(new InputStreamReader(in));
        outputStream = out;
    }

    public ForcedInput() {
        this(System.in, System.out);
    }

    public int inputInt(String msg) throws IOException {
        return (int)input(msg, intChain);
    }

    public int inputPositiveInt(String msg) throws IOException {
        return (int)input(msg, uIntChain);
    }

    public double inputDouble(String msg) throws IOException {
        return (double)input(msg, doubleChain);
    }

    public double inputDouble(String msg, double min, double max) throws IOException {
        doubleChain.addValidator(new RangeValidator("实数范围有误", min, max));
        double result = inputDouble(msg);
        doubleChain.removeValidator(0);
        return result;
    }

    public int inputInt(String msg, int min, int max) throws IOException {
        intChain.addValidator(new RangeValidator("整数范围有误", min, max));
        int result = inputInt(msg);
        intChain.removeValidator(0);
        return result;
    }

    public double inputPositiveDouble(String msg) throws IOException {
        return (double)input(msg, pDoubleChain);
    }

    public Object input(String prompt, ValidateChain chain) throws IOException {
        String raw;

        while(true) {
            String errMsg;
            outputStream.write(prompt.getBytes());

            raw = readLine();
            if(!chain.isValid(raw)) {
                errMsg = chain.getErrorMessage(raw);
                printlnMessage(errMsg);
            } else {
                break;
            }
        }

        Object v = null;
        try {
            v = chain.parse(raw);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return v;
    }

    public String readLine() throws IOException {
        return reader.readLine();
    }

    private void printlnMessage(String msg) throws IOException {
        outputStream.write((msg+"\n").getBytes());
    }

}
